#include "logger.h"
#include <memory>

#include "spdlog/async.h"
#include "spdlog/cfg/env.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_sinks.h"
class mylogger
{
   public:
    std::shared_ptr<spdlog::logger> instance;
};
SPDLogger::SPDLogger()
{
    my_logger_ = std::make_shared<mylogger>();
}

SPDLogger::~SPDLogger() {}

SPDLogger &SPDLogger::instance()
{
    static SPDLogger l;
    return l;
}

void SPDLogger::init(const std::string &name, const std::string &filepath, int level)
{
    try
    {

        auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(filepath, 1024 * 1024 * 64, 6);
        auto console_sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();

        file_sink->set_level(static_cast<spdlog::level::level_enum>(level));
        console_sink->set_level(static_cast<spdlog::level::level_enum>(level));

        my_logger_->instance = std::make_shared<spdlog::logger>(name, spdlog::sinks_init_list{file_sink, console_sink});
        my_logger_->instance->set_pattern("%Y-%m-%d %H:%M:%S.%e	%l [%n-%P] [%t] %v");
        my_logger_->instance->flush_on(spdlog::level::info);
        // 关键：设置logger本身的级别
        my_logger_->instance->set_level(static_cast<spdlog::level::level_enum>(level));

        spdlog::flush_every(std::chrono::seconds(2));
    }
    catch (const std::exception &e)
    {
        std::cout << "init log exception: " << e.what() << std::endl;
    }
    
    // try
    // {
    //     auto console_sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();
    //     my_logger_->instance = std::make_shared<spdlog::logger>(name, spdlog::sinks_init_list{console_sink});
    //     //my_logger_->instance = spdlog::stdout_logger_mt(name);
    //     //my_logger_->instance = spdlog::rotating_logger_mt(name, filepath, 1024 * 1024 * 64, 6);
    //     my_logger_->instance->set_pattern("%Y-%m-%d %H:%M:%S.%e	%l [%n-%P] [%t] %v");
    //     my_logger_->instance->flush_on(spdlog::level::info);
    //     // 关键：设置logger本身的级别
    //     my_logger_->instance->set_level(static_cast<spdlog::level::level_enum>(level));

    //     spdlog::flush_every(std::chrono::seconds(2));
    // }
    // catch (const std::exception &e)
    // {
    //     std::cout << "init log exception: " << e.what() << std::endl;
    // }
    
}

void SPDLogger::uninit()
{
    spdlog::shutdown();
}

void SPDLogger::setLoggerLevel(int level)
{
    auto sinks = my_logger_->instance->sinks();
    for(auto sink:sinks){
        if(std::dynamic_pointer_cast<spdlog::sinks::stdout_sink_mt>(sink)){
            std::cout<<"ignore stdout logger"<<std::endl;
            continue;
        }

        std::cout<<"set file logger level "<<level<<std::endl;
        auto level_enum = static_cast<spdlog::level::level_enum>(level);
        sink->set_level(static_cast<spdlog::level::level_enum>(level));
        std::cout<<"set file logger level "<<sink->level()<<std::endl;
    }    
}
void SPDLogger::setStdoutLoggerLevel(int level)
{
    auto sinks = my_logger_->instance->sinks();
    for(auto sink:sinks){
        if(std::dynamic_pointer_cast<spdlog::sinks::stdout_sink_mt>(sink)){
            std::cout<<"set console logger level "<<level<<std::endl;
            auto level_enum = static_cast<spdlog::level::level_enum>(level);
            sink->set_level(static_cast<spdlog::level::level_enum>(level));
            std::cout<<"set console logger level "<<sink->level()<<std::endl;
        }
    }
}

void SPDLogger::write(int level, const std::string &logText)
{
    try
    {
        if (my_logger_)
        {
            my_logger_->instance->log(static_cast<spdlog::level::level_enum>(level), logText);
        }
        else
        {
            std::cout << logText << std::endl;
        }
    }
    catch (...)
    {
        std::cout << logText << std::endl;
    }
}